package cn.iocoder.yudao.module.reading.service.community;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.reading.util.CommunityPermissionUtils;
import cn.iocoder.yudao.module.reading.util.CommunityValidationUtils;
import cn.iocoder.yudao.module.reading.controller.app.community.vo.comment.CommentCreateReqVO;
import cn.iocoder.yudao.module.reading.controller.app.community.vo.comment.CommentRespVO;
import cn.iocoder.yudao.module.reading.controller.app.community.vo.common.LikeToggleRespVO;
import cn.iocoder.yudao.module.reading.convert.community.CommunityCommentConvert;
import cn.iocoder.yudao.module.reading.dal.dataobject.community.CommunityCommentDO;
import cn.iocoder.yudao.module.reading.dal.dataobject.community.CommunityCommentLikeDO;
import cn.iocoder.yudao.module.reading.dal.mysql.community.CommunityCommentLikeMapper;
import cn.iocoder.yudao.module.reading.dal.mysql.community.CommunityCommentMapper;
import cn.iocoder.yudao.module.reading.dal.mysql.community.CommunityPostMapper;
import cn.iocoder.yudao.module.reading.dal.dataobject.user.UserDO;
import cn.iocoder.yudao.module.reading.service.user.UserService;
import cn.iocoder.yudao.module.reading.framework.util.StaticResourceUrlUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import jakarta.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.reading.enums.ErrorCodeConstants.*;

/**
 * 社区评论服务实现类
 *
 * @author 芋道源码
 */
@Service
@Slf4j
public class CommunityCommentServiceImpl implements CommunityCommentService {

    @Resource
    private CommunityCommentMapper commentMapper;

    @Resource
    private CommunityCommentLikeMapper commentLikeMapper;

    @Resource(name = "communityPostMapper")
    private CommunityPostMapper postMapper;

    @Resource
    private UserService userService;

    @Resource
    private WxContentSecurityService contentSecurityService;

    @Resource
    private CommunityLimitService limitService;

    @Resource
    private CommunityCountCacheService countCacheService;

    @Resource
    private StaticResourceUrlUtils staticResourceUrlUtils;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createComment(CommentCreateReqVO createReqVO, Long userId) {
        // 1. 参数校验
        CommunityValidationUtils.validateId(createReqVO.getPostId(), "帖子ID");
        CommunityValidationUtils.validateCommentContent(createReqVO.getContent());
        if (createReqVO.getParentId() != null) {
            CommunityValidationUtils.validateId(createReqVO.getParentId(), "父评论ID");
        }

        // 2. 校验帖子存在
        if (postMapper.selectById(createReqVO.getPostId()) == null) {
            throw exception(COMMUNITY_POST_NOT_EXISTS);
        }

        // 3. 检查评论频控
        var limitResult = limitService.checkCommentLimit(userId);
        if (!limitResult.getCanOperate()) {
            throw exception(COMMUNITY_COMMENT_LIMIT_EXCEEDED);
        }

        // 4. 内容安全检查
        var sensitiveResult = contentSecurityService.checkTextContent(createReqVO.getContent());
        if (sensitiveResult.getHasSensitive()) {
            throw exception(COMMUNITY_CONTENT_CONTAINS_SENSITIVE);
        }

        // 4. 转换并保存评论
        CommunityCommentDO comment = CommunityCommentConvert.INSTANCE.convert(createReqVO);
        comment.setUserId(userId);
        commentMapper.insert(comment);

        // 5. 更新帖子评论数（使用缓存）
        countCacheService.incrementPostCommentCount(createReqVO.getPostId(), 1);

        // 6. 如果是回复评论，更新父评论回复数
        if (createReqVO.getParentId() != null) {
            commentMapper.updateReplyCount(createReqVO.getParentId(), 1);
        }

        // 7. 记录评论操作（用于频控）
        limitService.recordCommentAction(userId);

        return comment.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteComment(Long id, Long userId) {
        // 1. 参数校验
        CommunityValidationUtils.validateId(id, "评论ID");

        // 2. 校验评论存在和权限
        CommunityCommentDO comment = validateCommentExists(id);
        CommunityPermissionUtils.validateCommentPermission(comment, userId);

        // 3. 删除评论（逻辑删除）
        commentMapper.deleteById(id);

        // 4. 更新帖子评论数（使用缓存）
        countCacheService.incrementPostCommentCount(comment.getPostId(), -1);

        // 5. 如果是回复评论，更新父评论回复数
        if (comment.getParentId() != null) {
            commentMapper.updateReplyCount(comment.getParentId(), -1);
        }
    }

    @Override
    public PageResult<CommentRespVO> getCommentPage(Long postId, PageParam pageParam, Long userId) {
        // 1. 分页查询评论
        PageResult<CommunityCommentDO> pageResult = commentMapper.selectPageByPostId(postId, pageParam);
        if (CollUtil.isEmpty(pageResult.getList())) {
            return PageResult.empty();
        }

        // 2. 获取用户信息
        List<Long> userIds = pageResult.getList().stream()
                .map(CommunityCommentDO::getUserId)
                .distinct()
                .collect(Collectors.toList());
        List<UserDO> users = userService.getUserList(userIds);
        Map<Long, UserDO> userMap = users.stream()
                .collect(Collectors.toMap(UserDO::getId, user -> user));

        // 3. 获取点赞状态
        final List<Boolean> likedList;
        if (userId != null) {
            List<Long> commentIds = pageResult.getList().stream()
                    .map(CommunityCommentDO::getId)
                    .collect(Collectors.toList());
            List<CommunityCommentLikeDO> likes = commentLikeMapper.selectByCommentIdsAndUserId(commentIds, userId);
            Map<Long, Boolean> likeMap = likes.stream()
                    .collect(Collectors.toMap(CommunityCommentLikeDO::getCommentId, like -> true));

            likedList = commentIds.stream()
                    .map(commentId -> likeMap.getOrDefault(commentId, false))
                    .collect(Collectors.toList());
        } else {
            likedList = null;
        }

        // 4. 转换返回（带URL转换）
        final List<CommunityCommentDO> commentDOList = pageResult.getList();
        List<CommentRespVO> commentList = commentDOList.stream()
                .map(comment -> {
                    UserDO user = userMap.get(comment.getUserId());
                    Boolean isLiked = likedList != null ?
                            likedList.get(commentDOList.indexOf(comment)) : false;
                    return CommunityCommentConvert.INSTANCE.convert(comment, user, isLiked, staticResourceUrlUtils);
                })
                .collect(Collectors.toList());

        return new PageResult<>(commentList, pageResult.getTotal());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public LikeToggleRespVO toggleCommentLike(Long commentId, Long userId) {
        // 1. 参数校验
        CommunityValidationUtils.validateId(commentId, "评论ID");

        // 2. 校验评论存在
        CommunityCommentDO comment = validateCommentExists(commentId);

        // 3. 先查询当前点赞状态
        CommunityCommentLikeDO existingLike = commentLikeMapper.selectByCommentIdAndUserId(commentId, userId);

        boolean isLiked;
        int likeCountIncrement;

        if (existingLike != null) {
            // 已点赞，取消点赞（使用物理删除）
            commentLikeMapper.deleteByCommentIdAndUserId(commentId, userId);
            isLiked = false;
            likeCountIncrement = -1;
        } else {
            // 未点赞，添加点赞
            CommunityCommentLikeDO like = CommunityCommentLikeDO.builder()
                    .commentId(commentId)
                    .userId(userId)
                    .build();
            commentLikeMapper.insert(like);
            isLiked = true;
            likeCountIncrement = 1;
        }

        // 4. 更新评论点赞数（使用缓存）
        Long newLikeCount = countCacheService.incrementCommentLikeCount(commentId, likeCountIncrement);

        // 5. 返回结果
        LikeToggleRespVO result = new LikeToggleRespVO();
        result.setIsLiked(isLiked);
        result.setLikeCount(newLikeCount.intValue());
        return result;
    }

    /**
     * 校验评论是否存在
     */
    private CommunityCommentDO validateCommentExists(Long id) {
        CommunityCommentDO comment = commentMapper.selectById(id);
        if (comment == null) {
            throw exception(COMMUNITY_COMMENT_NOT_EXISTS);
        }
        return comment;
    }

}
